<?php
// +----------------------------------------------------------------------
// | huicmf [ huicmf快速开发框架 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2022~2024 https://xiaohuihui.cc All rights reserved.
// +----------------------------------------------------------------------
// | Author: 小灰灰 <762229008@qq.com>
// +----------------------------------------------------------------------
// | Info:
// +----------------------------------------------------------------------

namespace plugin\admin\app\servicers;

use think\facade\Db;
use support\Request;

class DragdoneUpService
{

    const sortSpace = 1000;// 排序默认间距

    /**
     * 拖拽排序 后台处理逻辑
     *
     * @param Request        $request 接收的参数
     * @param \support\Model $model   被排序的表
     *
     * @return true
     */
    static function dragDoneUpData(Request $request, $model)
    {
        $primary_key = $model->getPk();
        // 获取前一条数据的 排序数值
        $params      = $request->post();
        $field       = $params['field'];
        $selfId      = $params[$primary_key];
        $afterWeight = $beforWeight = 0;
        if ($params['beforId']) {
            $beforWeight = $model->where($primary_key, $params['beforId'])->value($field);
        } else {
            // 不存在 则查询 后一个位置的前一条记录  先查询 后者的排序值
            $afterWeight = $model->where($primary_key, $params['afterId'])->value($field);

            $info = $model->where([[$field, '>', $afterWeight], [$primary_key, '<>', $selfId]])->order($field,
                'desc')->field($primary_key, $field)->find();
            if ($info) {
                $beforWeight       = $info[$field];
                $params['beforId'] = $info[$primary_key];
            } else {
                $beforWeight = -1;// 没有记录
            }
        }
        if ( ! $afterWeight) {
            if ($params['afterId']) {
                $afterWeight = $model->where($primary_key, $params['afterId'])->value($field);
            } else {
                $info = $model->where([[$field, '<', $beforWeight], [$primary_key, '<>', $selfId]])->order($field,
                    'desc')->field($primary_key, $field)->find();
                if ($info) {
                    $afterWeight       = $info[$field];
                    $params['afterId'] = $info[$primary_key];
                } else {
                    $afterWeight = -1;// 没有记录
                }
            }
        }

        // 间隔值太小  触发全表重排
        if (abs($afterWeight - $beforWeight) < 10 || ($beforWeight < 0 && $afterWeight < 10) || ($beforWeight < 10 && $afterWeight < 0)) {
            self::dragDoneUpDataDefault($model, $field);
            // 再次获取新的 排序数值
            $beforWeight = $model->where($primary_key, $params['beforId'])->value($field) ?: -1;
            $afterWeight = $model->where($primary_key, $params['afterId'])->value($field) ?: -1;
        }

        // 如果当前位置末尾没有数据了
        if ($afterWeight == -1) {
            $afterWeight = 0;
        }
        if ($beforWeight == -1) {
            // 如果当前位置前面没有数据了  则更新的排序值 = 最大的排序值+间隔值
            $newWeight = $afterWeight + self::sortSpace;
        } else {
            // 取中间值 则为当前数据的值
            $newWeight = ceil(($beforWeight + $afterWeight) / 2);
        }
//        Logger::debug(['取中间值',$newWeight,$beforWeight,$afterWeight,$params]);
        if ($newWeight < 2) {
//            throw new ApiException('抱歉，排序失败，取值错误');
        }
        // 更新排序
        $model->where($primary_key, $selfId)->update([$field => $newWeight]);

        return $newWeight;
    }

    /**
     * 全表重排排序
     *
     * @param                $model
     * @param                $field
     * @param                $sortSpace
     *
     * @return void
     */
    static protected function dragDoneUpDataDefault($model, $field)
    {
        $tableName   = $model->getTable();
        $primary_key = $model->getPk();
        $sortSpace   = self::sortSpace;
        Db::query("SET @row_number = 0");
        $sql = " UPDATE $tableName t1
                JOIN (
                    SELECT id, (@row_number := @row_number + 1) AS new_weight
                    FROM (
                        SELECT id, $field
                        FROM $tableName
                        ORDER BY $field asc,$primary_key asc
                    ) AS sorted_table
                ) AS t2 ON t1.id = t2.id
                SET t1.$field = t2.new_weight * $sortSpace";

        return Db::execute($sql);
    }

}
